﻿package ygg.encoding.amf
{
	import flash.utils.ByteArray;
	import flash.utils.getQualifiedClassName;
	import flash.xml.XMLDocument;
	
	import j.sus2maj7.encoding.*;
	
	import ygg.encoding.amf.*;
	import ygg.encoding.amf.type.*;
	import ygg.encoding.amf.type.v0.*;
	import ygg.encoding.amf.type.v3.*;
	
	public class AmfCodecFactory extends AbstractCodecFactory
	{
		public function AmfCodecFactory()
		{
			super();
		}
		
		public function getStringCodec(version:uint):ICodec
		{
			var retVal:ICodec;
			
			switch (version)
			{
				case AmfVersion.V3:
					retVal = new StringCodec();
					break;
				case AmfVersion.V0:
					//return new StringCodec();
					break;
				default:
					throw new Error("Invalid Version");
					break;
			}
			
			return retVal;
		}
		override public function getEncoder(o:*, context:IContext=null):ICodec
		{
			trace('TYPE', getQualifiedClassName(o));
			
			var retVal:ICodec;
			
			//trace( describeType(o) );
			
			if ( o === undefined )
			{
				trace('undefined');
				return new UndefinedCodec();
			}
			else if (o === null )
			{
				trace('null');
				return new NullCodec();
			}
			else if (o is Boolean )
			{
				if (o)
				{
					trace('true');
					return new TrueCodec();
				}
				else
				{
					trace('false');
					return new FalseCodec();
				}
			}
			else if (o is Number )
			{
				trace('Number');
				
				if (o is int && o < 0x10000000 && o > -0x10000000 )
				{
					trace('int');
					return new IntegerCodec();
				}
				else
				{
					trace('double');
					return new DoubleCodec();
				}
				
			}
			else if (o is String )
			{
				trace('String');
				return new StringCodec();
				
			}//*
			else if (o is Array )
			{
				trace('Array');
				
				return new ArrayCodec();
			}
			
			else if (o is XML )
			{
				trace('XML');
				return new XmlCodec();
				
			}
			else if (o is XMLDocument )
			{
				trace('XMLDocument');
				return new XmlDocCodec();
				
			}
			else if (o is Date )
			{
				trace('Date');
				return new DateCodec();
				
			}
			else if (o is ByteArray )
			{
				trace('ByteArray');
				return new ByteArrayCodec();
			}
			else
			{
				trace('Object');
				//Object
				return new ObjectCodec();
			}
			
			//if simple, write marker
			//if string
			
			//if complex
			
			return retVal;
		}
		override public function getDecoder(o:*,context:IContext=null):ICodec
		{
			var retVal:ICodec;
			var marker:uint = o as uint;
			
			if (AmfContext(context).version == AmfVersion.V3)
			{
				if (marker & 1)
				{
					switch (marker)
					{
						case Amf3Marker.TRUE :
							return new TrueCodec();
							break;
						case Amf3Marker.ARRAY :
							return new ArrayCodec();
							break;
						case Amf3Marker.NULL :
							return new NullCodec();
							break;
						case Amf3Marker.DOUBLE :
							return new DoubleCodec();
							break;
						case Amf3Marker.XML_ :
							return new XmlCodec();
							break;
						case Amf3Marker.XML_DOC :
							return new XmlDocCodec();
							break;
						default:
							throw new Error("Invalid Marker");
							break;
					}
				}
				else
				{
					switch (marker)
					{
						case Amf3Marker.INTEGER :
							return new IntegerCodec();
							break;
						case Amf3Marker.STRING :
							return new StringCodec();
							break;
						case Amf3Marker.FALSE :
							return new FalseCodec();
							break;
						case Amf3Marker.OBJECT :
							return new ObjectCodec();
							break;
						case Amf3Marker.DATE :
							return new DateCodec();
							break;
						case Amf3Marker.BYTEARRAY :
							return new ByteArrayCodec();
							break;
						case Amf3Marker.UNDEFINED :
							return new UndefinedCodec();
							break;
						default:
							throw new Error("Invalid Marker");
							break;
					}
				}
			}
			
			return retVal;
		}
	}
}